﻿using Frameworks;
using Networks;
using Networks.Data;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;

namespace game.lobby
{
    public class Lobby : MonoBehaviour
    {
        public GameObject uiCanvas;

        [Header("Chat")]
        public GameObject chat_plane;
        public Text chat_txt;
        public GameObject user_template;
        public InputField chat_InputField;
        public Button chat_btn;

        private List<UserEntity> _users;
        private List<ChatRecord> _chatRecords;
        private string _selectedUser;

        [Header("Room - Lobby")]
        public GameObject room_template;
        public Button creatRoom_btn;
        public Button joinRoom_btn;

        private List<RoomEntity> _rooms;
        private RoomData _selectedRoom;

        [Header("Room")]
        public GameObject room_plane;
        public Text roomName_txt;
        public GameObject player_template;
        public Button startGame_btn;
        public Button ready_btn;
        public Button leaveRoom_btn;

        private List<RoomSeatEntity> _roomSeats;
        private bool _isReady;

        [Header("Seat")]
        public GameObject playerPerfab;
        public Transform[] seats;
        private List<VRPlayerTest> _vrPlayers;

        [Header("bullet")]
        public GameObject bulletPrefab;

        private void Awake()
        {
            chat_plane.SetActive(true);
            _users = new List<UserEntity>();
            _chatRecords = new List<ChatRecord>();
            chat_btn.onClick.AddListener(sendChat);

            _rooms = new List<RoomEntity>();
            creatRoom_btn.onClick.AddListener(() => { reqCreateRoom(); });
            joinRoom_btn.onClick.AddListener(() => { if (_selectedRoom != null) reqJoinRoom(_selectedRoom.roomId); });
            // 查询房间列表后再显示创建/加入房间的按钮
            creatRoom_btn.gameObject.SetActive(false);
            joinRoom_btn.gameObject.SetActive(false);

            room_plane.SetActive(false);
            startGame_btn.gameObject.SetActive(false);
            _roomSeats = new List<RoomSeatEntity>();
            startGame_btn.onClick.AddListener(() => { reqStartGame(); });
            ready_btn.onClick.AddListener(() => { reqReady(); });
            leaveRoom_btn.onClick.AddListener(() => { reqLeaveRoom(); });
            _vrPlayers = new List<VRPlayerTest>();


            EventProxy.AddEventListener(Routes.LOBBY_NOTIFY_ADD, addUser);
            EventProxy.AddEventListener(Routes.LOBBY_NOTIFY_LEAVE, removeUser);
            EventProxy.AddEventListener(Routes.LOBBY_NOTIFY_CHAT, onChat);

            EventProxy.AddEventListener(Routes.ROOM_LIST, onRespRoomList);
            EventProxy.AddEventListener(Routes.ROOM_CREATE, onRespCreateRoom);
            EventProxy.AddEventListener(Routes.ROOM_JOIN, onRespJoinRoom);
            EventProxy.AddEventListener(Routes.ROOM_LEAVE, onRespLeaveRoom);
            EventProxy.AddEventListener(Routes.ROOM_PLAYER_ACTION, onRespPlayerAction);

            EventProxy.AddEventListener(Routes.ROOM_NOTIFY_STATE_CHANGFE, onRoomStateChange);
            EventProxy.AddEventListener(Routes.ROOM_NOTIFY_PLAYER_LEAVE, onPlayerLeave);

            EventProxy.AddEventListener(Routes.ROOM_NOTIFY_PLAYER_INFO, updatePlayerInfo);
            EventProxy.AddEventListener(Routes.ROOM_NOTIFY_PLAYER_STATE, updatePlayerState);

            EventProxy.AddEventListener(Routes.C2S_GAME_START, onRespStartGame);

            EventProxy.AddEventListener(Routes.S2C_GAME_LOAD, onGameLoading);
            EventProxy.AddEventListener(Routes.S2C_GAME_BEGIN, onGameBegin);

            EventProxy.AddEventListener(Routes.GAME_NOTIFY_ENTER_FRAME, onEnterFrame);
        }

        private void Start()
        {
            updateUsers();

            reqRoomList();
            //Invoke("reqRoomList", 1f);
        }

        private void Update()
        {
            for (int i = 0; i < _vrPlayers.Count; i++)
            {
                _vrPlayers[i]?.Update();
            }
        }

        private void FixedUpdate()
        {
            for (int i = 0; i < _vrPlayers.Count; i++)
            {
                _vrPlayers[i]?.FixedUpdate();
            }
        }

        private void OnDestroy()
        {
            EventProxy.RemoveEventListener(Routes.LOBBY_NOTIFY_ADD, addUser);
            EventProxy.RemoveEventListener(Routes.LOBBY_NOTIFY_LEAVE, removeUser);
            EventProxy.RemoveEventListener(Routes.LOBBY_NOTIFY_CHAT, onChat);

            EventProxy.RemoveEventListener(Routes.ROOM_LIST, onRespRoomList);
            EventProxy.RemoveEventListener(Routes.ROOM_CREATE, onRespCreateRoom);
            EventProxy.RemoveEventListener(Routes.ROOM_JOIN, onRespJoinRoom);
            EventProxy.RemoveEventListener(Routes.ROOM_LEAVE, onRespLeaveRoom);
            EventProxy.RemoveEventListener(Routes.ROOM_PLAYER_ACTION, onRespPlayerAction);

            EventProxy.RemoveEventListener(Routes.ROOM_NOTIFY_STATE_CHANGFE, onRoomStateChange);
            EventProxy.RemoveEventListener(Routes.ROOM_NOTIFY_PLAYER_LEAVE, onPlayerLeave);

            EventProxy.RemoveEventListener(Routes.ROOM_NOTIFY_PLAYER_INFO, updatePlayerInfo);
            EventProxy.RemoveEventListener(Routes.ROOM_NOTIFY_PLAYER_STATE, updatePlayerState);

            EventProxy.RemoveEventListener(Routes.C2S_GAME_START, onRespStartGame);

            EventProxy.RemoveEventListener(Routes.S2C_GAME_LOAD, onGameLoading);
            EventProxy.RemoveEventListener(Routes.S2C_GAME_BEGIN, onGameBegin);

            EventProxy.RemoveEventListener(Routes.GAME_NOTIFY_ENTER_FRAME, onEnterFrame);
        }

        #region User List
        private void updateUsers()
        {
            clearUsers();

            generateUser("All");
            _users[0].toggle.isOn = true;

            for (int i = 0; i < Game.Instance.users.Length; i++)
            {
                string userID = Game.Instance.users[i];
                if (userID == Game.Instance.myself.username) continue;
                generateUser(userID);
            }
        }

        private void generateUser(string username)
        {
            GameObject go = Instantiate(user_template, user_template.transform.parent);
            go.SetActive(true);

            Toggle toggle = go.GetComponent<Toggle>();
            Text label = go.transform.Find("Label").GetComponent<Text>();

            label.text = username;
            toggle.onValueChanged.AddListener(value =>
            {
                if (value) { _selectedUser = username; }
            });

            UserEntity userEntity = new UserEntity();
            userEntity.go = go;
            userEntity.toggle = toggle;
            userEntity.label = label;
            userEntity.user.username = username;
            _users.Add(userEntity);
        }

        private void clearUsers()
        {
            for (int i = 0; i < _users.Count; i++)
            {
                Destroy(_users[i].go);
            }
            _users.Clear();
        }

        private void addUser(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject user = eventData.target as JObject;
            string username = user["uid"].ToString();

            generateUser(username);

            chat_txt.text += string.Format("<color=yellow>{0}:加入房间\n</color>", username);
        }

        private void removeUser(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject user = eventData.target as JObject;
            string userID = user["uid"].ToString();

            //var userEntites = _users.Where(u => u.username == userID).ToList();
            var userEntity = _users.First(u => u.user.username == userID);
            if (userEntity != null)
            {
                if (userEntity.toggle.isOn)
                {
                    _users[0].toggle.isOn = true;
                }

                chat_txt.text += string.Format("<color=red>{0}:离开房间\n</color>", userEntity.user.username);

                _users.Remove(userEntity);
                Destroy(userEntity.go);
            }
        }
        #endregion

        #region Chat
        private void sendChat()
        {
            if (!string.IsNullOrEmpty(chat_InputField.text) && !string.IsNullOrEmpty(_selectedUser))
            {
                if (_selectedUser == "All")
                {
                    chat("*", chat_InputField.text);
                }
                else
                {
                    // Chat with someone only.
                    chat(_selectedUser, chat_InputField.text);
                }
                chat_InputField.text = string.Empty;
            }
        }

        private void chat(string target, string content)
        {
            JObject message = new JObject();
            message.Add("content", content);
            message.Add("from", Game.Instance.myself.username);
            message.Add("target", target);

            _chatRecords.Add(new ChatRecord(Game.Instance.myself.username, content));
            chat_txt.text += string.Format("{0}:{1}\n", Game.Instance.myself.username, content);

            NetworkManager.Instance.Request(Routes.LOBBY_CHAT_SEND, message);
        }

        private void onChat(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject message = eventData.target as JObject;

            JToken msg = null, fromName = null, targetName = null;
            if (message.TryGetValue("msg", out msg) &&
                message.TryGetValue("from", out fromName) &&
                message.TryGetValue("target", out targetName))
            {
                if (fromName.ToString() == Game.Instance.myself.username) return;

                //Debug.Log(fromName.ToString() + ":" + msg.ToString() + " to " + targetName.ToString());
                _chatRecords.Add(new ChatRecord(fromName.ToString(), msg.ToString()));
                chat_txt.text += string.Format("{0}:{1}\n", fromName.ToString(), msg.ToString());
            }
        }
        #endregion

        #region Room - Lobby
        private void reqRoomList()
        {
            NetworkManager.Instance.Request(Routes.ROOM_LIST, new JObject());
        }

        private void onRespRoomList(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject json_obj = eventData.target as JObject;
            if (json_obj.ContainsKey("roomList"))
            {
                RoomData[] roomDatas = JsonConvert.DeserializeObject<RoomData[]>(json_obj["roomList"].ToString());
                for (int i = 0; i < roomDatas.Length; i++)
                {
                    RoomData roomData = roomDatas[i];
                    generateRoom(roomData);
                }

                creatRoom_btn.gameObject.SetActive(true);
                joinRoom_btn.gameObject.SetActive(true);
            }

            if (_rooms.Count > 0)
            {
                _rooms[0].toggle.isOn = true;
                _selectedRoom = _rooms[0].room;
            }
            else _selectedRoom = null;
        }

        private void reqCreateRoom()
        {
            JObject message = new JObject();
            message.Add("roomType", (int)Networks.ROOM.TYPE.USER);
            message.Add("roomName", "TEST");
            message.Add("maxPlayers", 10);
            NetworkManager.Instance.Request(Routes.ROOM_CREATE, message);
        }

        private void onRespCreateRoom(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            // 创建成功则加入房间
            JObject json_obj = eventData.target as JObject;
            if (json_obj.ContainsKey("code"))
            {
                if (Convert.ToInt32(json_obj["code"]) == (int)Networks.GAME.RETURN_CODE.SUCCESS)
                {
                    int roomId = Convert.ToInt32(json_obj["roomId"]);
                    for (int i = 0; i < _rooms.Count; i++)
                    {
                        if (_rooms[i].room.roomId == roomId)
                        {
                            _selectedRoom = _rooms[i].room;
                            break;
                        }
                    }
                    reqJoinRoom(roomId);
                }
            }
        }

        private void onRoomStateChange(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject json_obj = eventData.target as JObject;

            Networks.ROOM.STATE roomState = (Networks.ROOM.STATE)Enum.Parse(typeof(Networks.ROOM.STATE), json_obj["type"].ToString());
            int roomId = Convert.ToInt32(json_obj["roomId"]);
            switch (roomState)
            {
                case Networks.ROOM.STATE.NONE:
                    break;
                case Networks.ROOM.STATE.CREATE:
                    RoomData roomData = new RoomData();
                    roomData.roomId = roomId;
                    roomData.roomName = json_obj["roomName"].ToString();
                    roomData.owner = json_obj["owner"].ToString();
                    roomData.maxPlayers = Convert.ToInt32(json_obj["maxPlayers"]);
                    generateRoom(roomData);

                    // 更新选择
                    if (_rooms.Count > 0)
                    {
                        _rooms[0].toggle.isOn = true;
                        _selectedRoom = _rooms[0].room;
                    }
                    else _selectedRoom = null;

                    break;
                case Networks.ROOM.STATE.REMOVE:
                    for (int i = 0; i < _rooms.Count; i++)
                    {
                        RoomEntity roomEntity = _rooms[i];
                        if (roomEntity.room.roomId == roomId)
                        {
                            _rooms.Remove(roomEntity);
                            Destroy(roomEntity.go);
                            break;
                        }
                    }

                    // 清空座位
                    for (int i = 0; i < _roomSeats.Count; i++)
                    {
                        RoomSeatEntity roomSeatEntity = _roomSeats[i];
                        //roomSeatEntity.Reset();
                        Destroy(roomSeatEntity.go);
                    }
                    _roomSeats.Clear();

                    // 关闭Room面板
                    chat_plane.SetActive(true);
                    room_plane.SetActive(false);
                    startGame_btn.gameObject.SetActive(false);

                    // 更新选择
                    if (_rooms.Count > 0)
                    {
                        _rooms[0].toggle.isOn = true;
                        _selectedRoom = _rooms[0].room;
                    }
                    else _selectedRoom = null;

                    Debug.Log("房间[" + roomId + "]解散");

                    break;
                case Networks.ROOM.STATE.UPDATE:
                    int playersNum = Convert.ToInt32(json_obj["playersNum"]);
                    int gameState = Convert.ToInt32(json_obj["gameState"]);
                    for (int i = 0; i < _rooms.Count; i++)
                    {
                        RoomEntity roomEntity = _rooms[i];
                        if (roomEntity.room.roomId == roomId)
                        {
                            roomEntity.room.playersNum = playersNum;
                            roomEntity.room.gameState = gameState;
                            roomEntity.roomStateChange();
                            break;
                        }
                    }
                    break;
                default:
                    break;
            }
        }

        private void reqJoinRoom(int roomId)
        {
            JObject message = new JObject();
            message.Add("roomId", roomId);
            NetworkManager.Instance.Request(Routes.ROOM_JOIN, message);
        }

        private void onRespJoinRoom(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject json_obj = eventData.target as JObject;
            if (json_obj.ContainsKey("code"))
            {
                if (Convert.ToInt32(json_obj["code"]) == (int)Networks.GAME.RETURN_CODE.SUCCESS)
                {
                    // 打开Room面板
                    roomName_txt.text = _selectedRoom.roomId + "-" + _selectedRoom.roomName;
                    for (int i = 0; i < _selectedRoom.maxPlayers; i++)
                    {
                        generateRoomSeat(i);
                    }
                    chat_plane.SetActive(false);
                    room_plane.SetActive(true);

                    // 通知服务器 enterRoomFinish
                    NetworkManager.Instance.Notify(Routes.C2S_ROOM_ENTER_FINISH, new JObject());
                }
            }
        }

        private void generateRoom(RoomData roomData)
        {
            GameObject go = Instantiate(room_template, room_template.transform.parent);
            go.SetActive(true);

            Toggle toggle = go.GetComponent<Toggle>();
            Text roomID = go.transform.Find("roomID").GetComponent<Text>();
            Text roomName = go.transform.Find("roomName").GetComponent<Text>();
            Text playersNum = go.transform.Find("playersNum").GetComponent<Text>();
            GameObject isPlaying = go.transform.Find("isPlaying").gameObject;

            roomID.text = roomData.roomId.ToString();
            roomName.text = roomData.roomName;
            toggle.onValueChanged.AddListener(value =>
            {
                if (value) { _selectedRoom = roomData; }
            });
            isPlaying.SetActive(false);

            RoomEntity roomEntity = new RoomEntity();
            roomEntity.go = go;
            roomEntity.toggle = toggle;
            roomEntity.roomID = roomID;
            roomEntity.roomName = roomName;
            roomEntity.playersNum = playersNum;
            roomEntity.isPlaying = isPlaying;
            roomEntity.room = roomData;
            roomEntity.roomStateChange();

            _rooms.Add(roomEntity);
        }
        #endregion

        #region Room
        private void generateRoomSeat(int seat)
        {
            GameObject go = Instantiate(player_template, player_template.transform.parent);
            go.SetActive(true);

            Image avatar = go.transform.Find("avatar").GetComponent<Image>();
            Text nickname = go.transform.Find("nickname").GetComponent<Text>();
            Text ready = go.transform.Find("ready").GetComponent<Text>();
            GameObject owner = go.transform.Find("owner").gameObject;

            owner.gameObject.SetActive(false);
            ready.text = string.Empty;
            nickname.text = "空位";

            RoomSeatEntity roomSeatEntity = new RoomSeatEntity();
            roomSeatEntity.go = go;
            roomSeatEntity.avatar = avatar;
            roomSeatEntity.nickname = nickname;
            roomSeatEntity.ready = ready;
            roomSeatEntity.owner = owner;
            roomSeatEntity.player.userID = "空位";
            roomSeatEntity.player.seat = seat;

            _roomSeats.Add(roomSeatEntity);
        }

        // 创建房间内的玩家资源
        private void updatePlayerInfo(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject json_obj = eventData.target as JObject;
            string userID = json_obj["uid"].ToString();
            int seat = Convert.ToInt32(json_obj["seat"]);

            _roomSeats[seat].player.userID = userID;
            _roomSeats[seat].avatar.color = Color.green;
            _roomSeats[seat].nickname.text = userID.ToString();

            Networks.PLAYER.STATE playerState = (Networks.PLAYER.STATE)Enum.Parse(typeof(Networks.PLAYER.STATE), json_obj["state"].ToString());
            for (int i = 0; i < _roomSeats.Count; i++)
            {
                RoomSeatEntity roomSeatEntity = _roomSeats[i];
                if (roomSeatEntity.player.userID == _selectedRoom.owner) // 激活房主标识
                {
                    roomSeatEntity.owner.SetActive(true);
                }

                if (Game.Instance.myself.username == _selectedRoom.owner) // 如果自己是房主,激活开始游戏按钮
                {
                    startGame_btn.gameObject.SetActive(true);
                    Game.Instance.isOwner = true;
                }

                if (roomSeatEntity.player.userID == Game.Instance.myself.username) // 记录自己的座位
                {
                    Game.Instance.seat = seat;
                }

                if (roomSeatEntity.player.userID == userID) // 显示准备状态
                {
                    switch (playerState)
                    {
                        case Networks.PLAYER.STATE.NONE:
                        case Networks.PLAYER.STATE.STANDUP:
                        case Networks.PLAYER.STATE.SITDOWN:
                            roomSeatEntity.ready.text = string.Empty;
                            roomSeatEntity.isReady = false;
                            if (userID == Game.Instance.myself.username)
                            {
                                ready_btn.GetComponentInChildren<Text>().text = "准备";
                            }
                            break;
                        case Networks.PLAYER.STATE.READY:
                            roomSeatEntity.ready.text = " 已准备";
                            roomSeatEntity.isReady = true;
                            if (userID == Game.Instance.myself.username)
                            {
                                ready_btn.GetComponentInChildren<Text>().text = "取消准备";
                            }
                            break;
                        case Networks.PLAYER.STATE.PLAYING: break;
                        case Networks.PLAYER.STATE.OFFLINE:
                            roomSeatEntity.ready.text = "离线";
                            roomSeatEntity.isReady = false;
                            ready_btn.gameObject.SetActive(false);
                            break;
                        case Networks.PLAYER.STATE.SEEING: break;
                        default: break;
                    }
                }
            }

            if (Game.Instance.isOwner)
            {
                for (int i = 0; i < _roomSeats.Count; i++)
                {
                    if (!_roomSeats[i].player.userID.Equals("空位") && !_roomSeats[i].isReady)
                    {
                        startGame_btn.interactable = false;
                        return;
                    }
                }
                startGame_btn.interactable = true;
            }
        }

        // 更新房间内的玩家信息
        private void updatePlayerState(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject json_obj = eventData.target as JObject;

            string userID = json_obj["uid"].ToString();
            Networks.PLAYER.STATE playerState = (Networks.PLAYER.STATE)Enum.Parse(typeof(Networks.PLAYER.STATE), json_obj["state"].ToString());
            for (int i = 0; i < _roomSeats.Count; i++)
            {
                RoomSeatEntity roomSeatEntity = _roomSeats[i];
                if (roomSeatEntity.player.userID == userID)
                {
                    switch (playerState)
                    {
                        case Networks.PLAYER.STATE.NONE:
                        case Networks.PLAYER.STATE.STANDUP:
                        case Networks.PLAYER.STATE.SITDOWN:
                            roomSeatEntity.ready.text = string.Empty;
                            roomSeatEntity.isReady = false;
                            if (userID == Game.Instance.myself.username)
                            {
                                _isReady = false;
                                ready_btn.GetComponentInChildren<Text>().text = "准备";
                            }
                            break;
                        case Networks.PLAYER.STATE.READY:
                            roomSeatEntity.ready.text = " 已准备";
                            roomSeatEntity.isReady = true;
                            if (userID == Game.Instance.myself.username)
                            {
                                _isReady = true;
                                ready_btn.GetComponentInChildren<Text>().text = "取消准备";
                            }
                            break;
                        case Networks.PLAYER.STATE.PLAYING: break;
                        case Networks.PLAYER.STATE.OFFLINE:
                            roomSeatEntity.ready.text = "离线";
                            roomSeatEntity.isReady = false;
                            ready_btn.gameObject.SetActive(false);
                            break;
                        case Networks.PLAYER.STATE.SEEING: break;
                        default: break;
                    }
                    break;
                }
            }

            if (Game.Instance.isOwner)
            {
                for (int i = 0; i < _roomSeats.Count; i++)
                {
                    if (!_roomSeats[i].player.userID.Equals("空位") && !_roomSeats[i].isReady)
                    {
                        startGame_btn.interactable = false;
                        return;
                    }
                }
                startGame_btn.interactable = true;
            }
        }

        private void reqReady()
        {
            JObject message = new JObject();
            message.Add("seat", Game.Instance.seat);
            message.Add("act", _isReady ? (int)Networks.PLAYER.ACTION.SITDOWN : (int)Networks.PLAYER.ACTION.READY);
            //NetworkManager.Instance.Request(Routes.ROOM_PLAYER_ACTION, message);
            NetworkManager.Instance.Notify(Routes.ROOM_PLAYER_ACTION, message);
        }

        private void reqLeaveRoom()
        {
            NetworkManager.Instance.Request(Routes.ROOM_LEAVE, new JObject());
        }

        private void onRespLeaveRoom(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject json_obj = eventData.target as JObject;
            if (json_obj.ContainsKey("code"))
            {
                if (Convert.ToInt32(json_obj["code"]) == (int)Networks.GAME.RETURN_CODE.SUCCESS)
                {
                    // 关闭Room面板
                    chat_plane.SetActive(true);
                    room_plane.SetActive(false);
                }
            }
        }

        private void onRespPlayerAction(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject json_obj = eventData.target as JObject;
            if (json_obj.ContainsKey("code"))
            {
                if (Convert.ToInt32(json_obj["code"]) == (int)Networks.GAME.RETURN_CODE.SUCCESS)
                {

                }
            }
        }

        private void onPlayerLeave(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject json_obj = eventData.target as JObject;
            int seat = Convert.ToInt32(json_obj["seat"]);
            //string userID = json_obj["uid"].ToString();
            for (int i = 0; i < _roomSeats.Count; i++)
            {
                RoomSeatEntity roomSeatEntity = _roomSeats[i];
                if (roomSeatEntity.player.seat == seat)
                {
                    roomSeatEntity.Reset();
                    break;
                }
            }

            if (Game.Instance.isOwner)
            {
                for (int i = 0; i < _roomSeats.Count; i++)
                {
                    if (!_roomSeats[i].player.userID.Equals("空位") && !_roomSeats[i].isReady)
                    {
                        startGame_btn.interactable = false;
                        return;
                    }
                }
                startGame_btn.interactable = true;
            }
        }
        #endregion

        #region Game
        private void reqStartGame()
        {
            NetworkManager.Instance.Request(Routes.C2S_GAME_START, new JObject());
        }

        private void onRespStartGame(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject json_obj = eventData.target as JObject;

        }

        private void onGameLoading(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject json_obj = eventData.target as JObject;
            for (int i = 0; i < _roomSeats.Count; i++)
            {
                RoomSeatEntity roomSeatEntity = _roomSeats[i];
                generatePlayer(roomSeatEntity.player);
            }
            uiCanvas.SetActive(false);

            // 通知服务器场景资源加载完成
            enterSceneFinish();
        }

        private void enterSceneFinish()
        {
            JObject message = new JObject();
            message.Add("seat", Game.Instance.seat);
            NetworkManager.Instance.Notify(Routes.C2S_GAME_ENTER_SCENE_FINISH, message);
        }

        private void onGameBegin(EventData eventData)
        {
            for (int i = 0; i < _vrPlayers.Count; i++)
            {
                VRPlayerTest vrPlayer = _vrPlayers[i];
                if (vrPlayer.playerData.userID == Game.Instance.myself.username)
                {
                    vrPlayer.Head.GetComponent<AIRandMove>().enabled = true;
                    vrPlayer.LeftArm.GetComponent<AIRandMove>().enabled = true;
                    vrPlayer.RightArm.GetComponent<AIRandMove>().enabled = true;
                    vrPlayer.LeftLeg.GetComponent<AIRandMove>().enabled = true;
                    vrPlayer.RightLeg.GetComponent<AIRandMove>().enabled = true;

                    vrPlayer.StartSync();
                    break;
                }
            }
        }

        private void generatePlayer(PlayerData playerData)
        {
            if (!playerData.userID.Equals("空位"))
            {
                GameObject playerGo = Instantiate(playerPerfab, seats[playerData.seat]);
                TMPro.TextMeshPro name = playerGo.transform.Find("name").GetComponent<TMPro.TextMeshPro>();
                name.text = playerData.userID;
                if (playerData.userID == Game.Instance.myself.username)
                {
                    name.color = Color.green;
                }

                VRPlayerTest vrPlayerTest = new VRPlayerTest();
                vrPlayerTest.entity = playerGo;
                vrPlayerTest.playerData = playerData;
                vrPlayerTest.Init(bulletPrefab);

                vrPlayerTest.DontSync(); // gameBegin后开始同步
                _vrPlayers.Add(vrPlayerTest);
            }
        }
        #endregion

        #region Player
        private void onEnterFrame(EventData eventData)
        {
            if (eventData == null || eventData.target == null) return;

            JObject json_obj = eventData.target as JObject;
            //Debug.Log(json_obj.ToString());

            int frame = Convert.ToInt32(json_obj["frameId"]);

            if (!json_obj.ContainsKey("frameMsg")) return;
            JArray frameMsgArray = json_obj["frameMsg"] as JArray;
            for (int i = 0; i < frameMsgArray.Count; i++)
            {
                JObject frameMsg = frameMsgArray[i] as JObject;
                string uid = frameMsg["uid"].ToString();

                if (!frameMsg.ContainsKey("msg")) return;
                JArray msgArray = frameMsg["msg"] as JArray;

                for (int j = 0; j < msgArray.Count; j++)
                {
                    JObject msg = msgArray[j] as JObject;

                    //int act = Convert.ToInt32(msg["act"]);
                    Networks.PLAYER.ACTION action = (Networks.PLAYER.ACTION)Enum.Parse(typeof(Networks.PLAYER.ACTION), msg["act"].ToString());

                    // 同步坐标时忽略自己
                    if (uid == Game.Instance.myself.username &&
                      (action == Networks.PLAYER.ACTION.SYNC_HEAD ||
                       action == Networks.PLAYER.ACTION.SYNC_LEFT_ARM ||
                       action == Networks.PLAYER.ACTION.SYNC_RIGHT_ARM ||
                       action == Networks.PLAYER.ACTION.SYNC_LEFT_LEG ||
                       action == Networks.PLAYER.ACTION.SYNC_RIGHT_LEG))
                    {
                        continue;
                    }

                    for (int n = 0; n < _vrPlayers.Count; n++)
                    {
                        VRPlayerTest vrPlayer = _vrPlayers[n];
                        if (uid == vrPlayer.playerData.userID)
                        {
                            switch (action)
                            {
                                case Networks.PLAYER.ACTION.SITDOWN:
                                    break;
                                case Networks.PLAYER.ACTION.STANDUP:
                                    break;
                                case Networks.PLAYER.ACTION.READY:
                                    break;
                                case Networks.PLAYER.ACTION.SYNC_HEAD:
                                    if (msg.ContainsKey("data"))
                                    {
                                        var data = msg["data"];
                                        float p_x = Convert.ToInt32(data["p_x"]) / 10000f;
                                        float p_y = Convert.ToInt32(data["p_y"]) / 10000f;
                                        float p_z = Convert.ToInt32(data["p_z"]) / 10000f;
                                        float r_x = Convert.ToInt32(data["r_x"]) / 10000f;
                                        float r_y = Convert.ToInt32(data["r_y"]) / 10000f;
                                        float r_z = Convert.ToInt32(data["r_z"]) / 10000f;

                                        vrPlayer.HeadPosition = new Vector3(p_x, p_y, p_z);
                                        vrPlayer.HeadRotation = Quaternion.Euler(r_x, r_y, r_z);
                                    }
                                    break;
                                case Networks.PLAYER.ACTION.SYNC_LEFT_ARM:
                                    if (msg.ContainsKey("data"))
                                    {
                                        var data = msg["data"];
                                        float p_x = Convert.ToInt32(data["p_x"]) / 10000f;
                                        float p_y = Convert.ToInt32(data["p_y"]) / 10000f;
                                        float p_z = Convert.ToInt32(data["p_z"]) / 10000f;
                                        float r_x = Convert.ToInt32(data["r_x"]) / 10000f;
                                        float r_y = Convert.ToInt32(data["r_y"]) / 10000f;
                                        float r_z = Convert.ToInt32(data["r_z"]) / 10000f;

                                        vrPlayer.LeftArmPosition = new Vector3(p_x, p_y, p_z);
                                        vrPlayer.LeftArmRotation = Quaternion.Euler(r_x, r_y, r_z);
                                    }
                                    break;
                                case Networks.PLAYER.ACTION.SYNC_RIGHT_ARM:
                                    if (msg.ContainsKey("data"))
                                    {
                                        var data = msg["data"];
                                        float p_x = Convert.ToInt32(data["p_x"]) / 10000f;
                                        float p_y = Convert.ToInt32(data["p_y"]) / 10000f;
                                        float p_z = Convert.ToInt32(data["p_z"]) / 10000f;
                                        float r_x = Convert.ToInt32(data["r_x"]) / 10000f;
                                        float r_y = Convert.ToInt32(data["r_y"]) / 10000f;
                                        float r_z = Convert.ToInt32(data["r_z"]) / 10000f;

                                        vrPlayer.RightArmPosition = new Vector3(p_x, p_y, p_z);
                                        vrPlayer.RightArmRotation = Quaternion.Euler(r_x, r_y, r_z);
                                    }
                                    break;
                                case Networks.PLAYER.ACTION.SYNC_LEFT_LEG:
                                    if (msg.ContainsKey("data"))
                                    {
                                        var data = msg["data"];
                                        float p_x = Convert.ToInt32(data["p_x"]) / 10000f;
                                        float p_y = Convert.ToInt32(data["p_y"]) / 10000f;
                                        float p_z = Convert.ToInt32(data["p_z"]) / 10000f;
                                        float r_x = Convert.ToInt32(data["r_x"]) / 10000f;
                                        float r_y = Convert.ToInt32(data["r_y"]) / 10000f;
                                        float r_z = Convert.ToInt32(data["r_z"]) / 10000f;

                                        vrPlayer.LeftLegPosition = new Vector3(p_x, p_y, p_z);
                                        vrPlayer.LeftLegRotation = Quaternion.Euler(r_x, r_y, r_z);
                                    }
                                    break;
                                case Networks.PLAYER.ACTION.SYNC_RIGHT_LEG:
                                    if (msg.ContainsKey("data"))
                                    {
                                        var data = msg["data"];
                                        float p_x = Convert.ToInt32(data["p_x"]) / 10000f;
                                        float p_y = Convert.ToInt32(data["p_y"]) / 10000f;
                                        float p_z = Convert.ToInt32(data["p_z"]) / 10000f;
                                        float r_x = Convert.ToInt32(data["r_x"]) / 10000f;
                                        float r_y = Convert.ToInt32(data["r_y"]) / 10000f;
                                        float r_z = Convert.ToInt32(data["r_z"]) / 10000f;

                                        vrPlayer.RightLegPosition = new Vector3(p_x, p_y, p_z);
                                        vrPlayer.RightLegRotation = Quaternion.Euler(r_x, r_y, r_z);
                                    }
                                    break;
                                case Networks.PLAYER.ACTION.SHOT:
                                    vrPlayer.onShot();
                                    break;
                                case Networks.PLAYER.ACTION.STOP_SHOT:
                                    vrPlayer.onStopShot();
                                    break;
                                case Networks.PLAYER.ACTION.SEEING:
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                }
            }
        }
        #endregion
    }

    internal class UserEntity
    {
        public GameObject go;
        public Toggle toggle;
        public Text label;

        public UserData user;

        public UserEntity()
        {
            user = new UserData();
        }
    }

    internal class RoomEntity
    {
        public GameObject go;
        public Toggle toggle;
        public Text roomID;
        public Text roomName;
        public Text playersNum;
        public GameObject isPlaying;

        public RoomData room;

        public RoomEntity()
        {
            room = new RoomData();
        }

        public void roomStateChange()
        {
            playersNum.text = string.Format("{0}/{1}", room.playersNum, room.maxPlayers);

            if (room.gameState == (int)Networks.ROOM.GAME_STATE.LOADING ||
                room.gameState == (int)Networks.ROOM.GAME_STATE.PLAYING)
            {
                isPlaying.SetActive(true);
            }
            else
            {
                isPlaying.SetActive(false);
            }
        }
    }

    internal class RoomSeatEntity
    {
        public GameObject go;
        public Image avatar;
        public Text nickname;
        public Text ready;
        public GameObject owner;

        public bool isReady;
        public PlayerData player;

        public RoomSeatEntity()
        {
            player = new PlayerData();
        }

        public void Reset()
        {
            avatar.color = Color.white;
            ready.text = string.Empty;
            nickname.text = "空位";
            player.userID = "空位";
            owner.SetActive(false);
            isReady = false;
        }
    }
}